/*
 * Copyright (c) 2024 Black Sesame Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "dal_cyclonedds/utils/TopicSertypeManager.hpp"

TopicSertypeManager* TopicSertypeManager::singleton_ = nullptr;

TopicSertypeManager::TopicSertypeManager() {}

TopicSertypeManager* TopicSertypeManager::GetInstance()
{
    if (singleton_ == nullptr) {
        singleton_ = new TopicSertypeManager();
    }
    return singleton_;
}

void TopicSertypeManager::AddTopicSerType(const dds_entity_t& participant,
                                          const std::string& type_name,
                                          struct sertype_dal* descriptor_ptr)
{
    std::lock_guard<std::mutex> lkg(mutex_);
    if (sertype_map_.find(participant) == sertype_map_.end()) {
        sertype_map_.insert({participant, std::unordered_map<std::string, struct sertype_dal*>()});
    }
    sertype_map_[participant][type_name] = descriptor_ptr;
}

void TopicSertypeManager::RemoveTopicSerType(const dds_entity_t& participant,
                                             const std::string& type_name)
{
    std::lock_guard<std::mutex> lkg(mutex_);
    if (sertype_map_.find(participant) != sertype_map_.end()) {
        sertype_map_[participant].erase(type_name);
    }
}

void TopicSertypeManager::RemoveTopicSerTypeByTypeName(const std::string& type_name)
{
    std::lock_guard<std::mutex> lkg(mutex_);
    for (auto& item : sertype_map_) {
        if (item.second.find(type_name) != item.second.end()) {
            item.second.erase(type_name);
        }
    }
}

struct sertype_dal* TopicSertypeManager::GetTopicSerType(const dds_entity_t& participant,
                                                         const std::string& type_name)
{
    std::lock_guard<std::mutex> lkg(mutex_);
    if (sertype_map_.find(participant) != sertype_map_.end()) {
        if (sertype_map_[participant].find(type_name) != sertype_map_[participant].end()) {
            return sertype_map_[participant][type_name];
        }
    }
    return nullptr;
}

void TopicSertypeManager::RemoveParticipant(const dds_entity_t& participant)
{
    std::lock_guard<std::mutex> lkg(mutex_);
    if (sertype_map_.find(participant) != sertype_map_.end()) {
        sertype_map_[participant].clear();
        sertype_map_.erase(participant);
    }
}

void TopicSertypeManager::AddTopicName(const dds_entity_t& participant,
                                       const std::string& topic_name)
{
    topic_map_[participant].insert(topic_name);
}

bool TopicSertypeManager::IsTopicNameExist(const dds_entity_t& participant,
                                           const std::string& topic_name)
{
    auto it = topic_map_.find(participant);
    if (it != topic_map_.end()) {
        return it->second.count(topic_name) > 0;
    }
    return false;
}

void TopicSertypeManager::RemoveTopicName(const dds_entity_t& participant,
                                          const std::string& topic_name)
{
    auto it = topic_map_.find(participant);
    if (it != topic_map_.end()) {
        it->second.erase(topic_name);
    }
}

void TopicSertypeManager::AddTopicInfo(const dds_entity_t& topic,
                                       const std::string& topic_name,
                                       const std::string& type_name)
{
    topic_info_map_[topic] = std::make_tuple(topic_name, type_name);
}

void TopicSertypeManager::DeleteTopicInfo(const dds_entity_t& topic)
{
    topic_info_map_.erase(topic);
}

std::string TopicSertypeManager::GetTopicName(const dds_entity_t& topic)
{
    auto it = topic_info_map_.find(topic);
    if (it != topic_info_map_.end()) {
        return std::get<0>(it->second);
    }
    return "";
}

std::string TopicSertypeManager::GetTypeName(const dds_entity_t& topic)
{
    auto it = topic_info_map_.find(topic);
    if (it != topic_info_map_.end()) {
        return std::get<1>(it->second);
    }
    return "";
}

void TopicSertypeManager::AddEntityToParticipant(const dds_entity_t& participant,
                                                 const dds_entity_t& entity)
{
    participant_entities_map_[participant].insert(entity);
}

void TopicSertypeManager::RemoveEntityFromParticipant(const dds_entity_t& participant,
                                                      const dds_entity_t& entity)
{
        auto it = participant_entities_map_.find(participant);
    if (it != participant_entities_map_.end()) {
        it->second.erase(entity);
    }
}

bool TopicSertypeManager::IsParticipantEntity(const dds_entity_t& participant,
                                              const dds_entity_t& entity)
{
    auto it = participant_entities_map_.find(participant);
    if (it != participant_entities_map_.end()) {
        return it->second.count(entity) > 0;
    }
    return false;
}

bool TopicSertypeManager::IsParticipantNoEntity(const dds_entity_t& participant)
{
    auto it = participant_entities_map_.find(participant);
    if (it != participant_entities_map_.end()) {
        return it->second.empty();
    }
    return true;
}
